package morenoapp.components.thinkgraphv2.nodes;

import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolo.nodes.PText;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.geom.Point2D;
import java.beans.PropertyChangeEvent;
import morenoapp.components.thinkgraph.node.WithTooltip;
import morenoapp.components.thinkgraphv2.nodes.partial.PVector;
import morenoapp.model.enums.MorenoSex;
import morenoapp.model.data.MorenoRespondentFace;
import morenoapp.model.view2.MorenoView2Face;

/**
 *
 * @author dmitry.mamonov
 */
public class RespondentItemNode extends AbstractNode implements WithTooltip {
    //model
    protected MorenoRespondentFace respondent;
    //visual
    protected PPath back = null;
    /**
     * Цвет фона которым следует отображать данный узел.
     */
    Color defaultPaint = Color.WHITE;
    /**
     * Текстовая метка содержащая номер респондента по порядку,
     * опционально его имя и другую информацию.
     */
    protected PText text = null;
    /**
     * Корректировка указывает на круг в социограмме,
     * в котором должен распологаться данный узел.
     */
    PVector correction = null;

    public RespondentItemNode(MorenoView2Face _config, MorenoRespondentFace _respondent) {
        super(_config);
        assert _respondent != null;
        this.respondent = _respondent;
        propertyChange(null);
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        removeAllChildren();

        //getting respondent position
        Point2D position = config.getRespondentPosition(respondent);

        { // hide male-female
            if (respondent.getSex() == MorenoSex.MALE && config.isHideMale()) {
                return;
            }
            if (respondent.getSex() == MorenoSex.FEMALE && config.isHideFemale()) {
                return;
            }
            if (config.isHideRespondent(respondent) == true) {
                return;
            }
        }

        { // display sex
            MorenoSex displaySex = config.isDisplaySex() ? respondent.getSex() : MorenoSex.UNKNOWN;
            switch (displaySex) {
                case MALE:
                    back = PPath.createRectangle(-15, -15, 30, 30);
                    break;
                case FEMALE:
                    back = PPath.createEllipse(-15, -15, 30, 30);
                    break;
                default:
                    back = createOctaedr(30);
                    back.setStroke(new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f, new float[]{2, 0, 1, 2}, 0));
                    break;
            }
            back.setOffset(0, 0);
            addChild(back);
        }

        { // display names
            if (text == null) {
                text = new PText();
            }
            if (config.isDisplayNames()) {
                text.setText(respondent.getName());
            } else {
                text.setText(String.valueOf(1 + respondent.getIndex()));
            }
            text.setOffset(-text.getWidth() / 2, -text.getHeight() / 2);
            addChild(text);
        }

        { // apply position
            super.setOffset(position);
        }
    }

    @Override
    public void translate(double dx, double dy) {
        super.translate(dx, dy);
        config.setRespondentPosition(respondent, getOffset());
    }

    @Override
    public String getTooltipText() {
        return respondent.getName();
    }



    protected static PPath createOctaedr(float size) {
        float size2 = size / 2.0f;
        float radii = (float) (size2 / Math.sin(Math.PI * 2.0 / 3.0));
        double alpha = Math.PI / 8.0;
        double twoPi = Math.PI * 2.0;
        double pi4 = Math.PI / 4.0;

        Point2D[] points = new Point2D[9];
        int index = 0;
        while (alpha < twoPi) {
            points[index] = new Point2D.Double(
                    Math.cos(alpha) * radii,
                    Math.sin(alpha) * radii);

            alpha += pi4;
            index++;
        }
        points[8] = points[0];
        return PPath.createPolyline(points);
    }
}
